﻿using Grpc.Core;
using Grpc.Core.Interceptors;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using SharedKernel.Infrastructure.Comm;
using SharedKernel.Infrastructure.Comm.Helpers;
using SharedKernel.Infrastructure.Grpc.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Grpc.Core.Metadata;

namespace SharedKernel.Infrastructure.Grpc.Interceptors
{
    /// <summary>
    /// 自定义的Grpc服务端授权拦截器
    /// </summary>
    public class GrpcServiceAuthorizationInterceptor : Interceptor
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IUserContext _userContext;
        private readonly IConfiguration _configuration;
        public GrpcServiceAuthorizationInterceptor(IHttpContextAccessor httpContextAccessor, IUserContext userContext, IConfiguration configuration)
        {
            //_authHeaderProvider = authHeaderProvider;
            _httpContextAccessor=httpContextAccessor;
            _userContext=userContext;
            _configuration=configuration;
        }

        /// <summary>
        /// 拦截客户端->服务端（单向请求）
        /// </summary>
        /// <typeparam name="TRequest"></typeparam>
        /// <typeparam name="TResponse"></typeparam>
        /// <param name="request"></param>
        /// <param name="context"></param>
        /// <param name="continuation"></param>
        /// <returns></returns>
        /// <exception cref="RpcException"></exception>
        public override Task<TResponse> UnaryServerHandler<TRequest, TResponse>(TRequest request, ServerCallContext context, UnaryServerMethod<TRequest, TResponse> continuation)
        {
            //这里面的Key都是小写的
            var authorizationEntry = context.RequestHeaders.FirstOrDefault(x => x.Key == "authorization");
            var sm3Entry = context.RequestHeaders.FirstOrDefault(x => x.Key == "sm3");
            var serverNameEntry = context.RequestHeaders.FirstOrDefault(x => x.Key == "servicename");
            if (authorizationEntry==null||sm3Entry==null||serverNameEntry==null)
            {
                throw new RpcException(new Status(StatusCode.Unauthenticated, "当前服务未被授权"));
            }

            var authorizationStr = authorizationEntry.Value.ToString();
            var sm3Str = sm3Entry.Value.ToString();
            var serverNameStr = serverNameEntry.Value.ToString();

            if (string.IsNullOrWhiteSpace(authorizationStr) || string.IsNullOrWhiteSpace(sm3Str) || string.IsNullOrWhiteSpace(serverNameStr))
            {
                throw new RpcException(new Status(StatusCode.Unauthenticated, "服务授权参数错误"));
            }

            var clientOptions = _configuration.GetSection($"GrpcClients:{serverNameEntry.Value.ToString()}").Get<GrpcClientOptions>();
            if (clientOptions == null||string.IsNullOrWhiteSpace(clientOptions.AuthorizationCode))
            {
                throw new RpcException(new Status(StatusCode.Unauthenticated, $"请求微服务配置信息丢失"));
            }
             
            //加上秘钥加密后的SM3值
            string sm3 = BouncyCastleHelper.SM3Hash(authorizationStr+clientOptions.AuthorizationCode);
            if (sm3!= sm3Str)
            {
                throw new RpcException(new Status(StatusCode.Unauthenticated, $"无效的秘钥"));
            }

            return base.UnaryServerHandler(request, context, continuation);
        }

    }
}
